/******************************************************************************
 * \brief	缓存队列（先进先出的系统缓存）的实现
 * \details	可以用作各个模块间的数据缓冲
 * \author	将狼才鲸
 * \date	2023-03-08
 ******************************************************************************/

#ifndef _QUEUE_BUFFER_H_
#define _QUEUE_BUFFER_H_

#include "queue.h"
#include <stdint.h>	/* uint32_t... */

#define QBUF_MARK		0xAABBCCDD	/* 魔术字 */
#define QBUF_ISVALID(x)	((x) && (x->mark == QBUF_MARK))

/* 当前缓存携带的参数 */
#define SYS_BUF_FLAG_MARK	(0x000000FF)
#define SYS_BUF_FLAG_SOF	(0x00000001)	/* 文件开始 */
#define SYS_BUF_FLAG_EOF	(0x00000002)	/* 文件结束 */
/* 顺延的值为0x00000004 0x00000008 0x00000010 0x00000020... */

/* 缓存的来源 */
enum {
	QBUF_TYPE_MALLOC,	/* 使用malloc为每个缓存分配空间 */
	QBUF_TYPE_ARRAY		/* 使用静态数组为每个缓存分配空间 */
};

/* 缓存的分类 */
enum {
	QBUF_GROUP_FREE,	/* 已释放的缓存 */
	QBUF_GROUP_DATBUF,	/* 数据缓存 */
	QBUF_GROUP_MSGBUF,	/* 消息缓存 */
	QBUF_GROUP_TMPBUF,	/* 临时缓存，用完即退回 */
	QBUF_GROUP_COUNT	/* 缓存分类的组别数 */
};

/* 初始化整个缓存时的参数 */
typedef struct _qbuf_group_cfg {
	uint32_t type;	/* QBUF_TYPE_MALLOC... */
	uint32_t count;	/* 该组内缓存总个数 */
	uint32_t unitsize;	/* 每个缓存元素的最大容量 */
	char *addr;		/* 整块缓存的起始地址 */
} qbuf_group_cfg_t;

/* 单个缓存 */
typedef struct _qbuf {
	queue_t queue;	/* 队列节点 */
	uint32_t mark;	/* 用魔术字标识该缓存正常 */
	uint32_t flags;	/* 标识该缓存的类型，如文件结尾 */
	uint32_t group;	/* 属于哪一组缓存（可以移动到别的组别） */
	char *addr;		/* 当前缓存的地址 */
	uint32_t size;	/* 缓存总大小 */
	uint32_t offset;/* 有效数据的起始位置 */
	uint32_t len;	/* 有效数据的长度 */
	uint32_t id;	/* 缓存的序号 */
	uint64_t user;	/* 私有数据，做拓展用 */
} qbuf_t;

/**
 * \brief	将系统中所有缓存都推到已释放队列中，等待进一步初始化
 */
extern void qbuf_init(void);

/**
 * \brief	初始化一个缓存组，分配好组内所有的缓存
 * \param	qg:	该组的配置参数
 * \param	queue_entry:	该组的类型
 */
extern int qbuf_group_cfg(qbuf_group_cfg_t *qg, uint32_t group);

/**
 * \brief 从该组内获取一个缓存，并初始化缓存的参数，这个缓存在用完后要记得释放回去
 */
extern qbuf_t *qbuf_alloc(uint32_t group);

/**
 * \brief	缓存用完后重新释放回该组的已释放队列中
 */
extern int qbuf_free(qbuf_t *buf);

/**
 * \brief	将数据发送到该组已使用队列中
 */
extern int qbuf_put(qbuf_t *buf);

/**
 * \brief	从该组已使用队列中获取一个有有效数据的缓存
 */
extern qbuf_t *qbuf_get(uint32_t group);

#endif /* _QUEUE_BUFFER_H_ */
